﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Linq.Dynamic;
using System.Collections;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Suucha.Expressions
{


    public static class SuuchaExpressionExtentions
    {
        /// <summary>
        /// 支持SuuchaExpression的Where扩展方法
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="source">源Queryable</param>
        /// <param name="expression">条件表达式</param>
        /// <returns>返回IQueryable</returns>
        public static IQueryable<T> Where<T>(this IQueryable<T> source, SuuchaExpression expression)
        {
            if (expression == null)
            {
                return source;
            }

            var collectionList = GetCollectionProperty(expression, source.ElementType);
            ParameterExpression pe = null;
            Expression exp = null;
            Type sourceType = source.ElementType;
            if (collectionList != null && collectionList.Count > 0)
            {
                if (collectionList.Count > 1)
                {
                    throw new InvalidOperationException(Resources.Resource("只支持一个集合属性"));
                }
                var setType = collectionList[0];
                Type collectionType = setType.Type;

                DynamicProperty p1 = new DynamicProperty(sourceType.Name, sourceType);
                DynamicProperty p2 = new DynamicProperty(setType.Name, collectionType);
                Type resultType = System.Linq.Dynamic.DynamicExpression.CreateClass(p1, p2);
                ParameterExpression collectionPe = Expression.Parameter(sourceType, "set");
                PropertyInfo collectionPi = sourceType.GetPropertyEx(setType.Name);
                Expression collectionExp = Expression.Property(collectionPe, collectionPi);
                ParameterExpression dynamicPe1 = Expression.Parameter(sourceType, "pe1");
                ParameterExpression dynamicPe2 = Expression.Parameter(collectionType, "pe2");
                ParameterExpression dynamicPe3 = Expression.Parameter(resultType, "pe3");

                Expression dynamicConstrator = Expression.MemberInit(Expression.New(resultType),
                    new MemberBinding[]{Expression.Bind(resultType.GetPropertyEx(sourceType.Name),dynamicPe1),
                    Expression.Bind(resultType.GetPropertyEx(setType.Name), dynamicPe2)});
                Type et = typeof(IEnumerable<>).MakeGenericType(collectionType);
                Type dt1 = typeof(Func<,>).MakeGenericType(sourceType, et);
                var ce = Expression.Lambda(dt1, collectionExp, collectionPe);
                Type dt2 = typeof(Func<,,>).MakeGenericType(sourceType, collectionType, resultType);
                Expression dynamicExpression = Expression.Lambda(dt2, dynamicConstrator, dynamicPe1, dynamicPe2);
                var selectMany = source.Provider.CreateQuery(
                    Expression.Call(
                    typeof(Queryable), "SelectMany",
                    new Type[] { sourceType, collectionType, resultType },
                    source.Expression, Expression.Quote(ce), Expression.Quote(dynamicExpression)));
                pe = Expression.Parameter(resultType, "it");
                exp = ToExpression(expression, resultType, pe, null, sourceType.Name, setType.Name);
                Type dt3 = typeof(Func<,>).MakeGenericType(resultType, typeof(bool));
                selectMany = selectMany.Provider.CreateQuery(
                    Expression.Call(
                    typeof(Queryable), "Where",
                    new Type[] { resultType },
                    selectMany.Expression, Expression.Quote(Expression.Lambda(dt3, exp, pe))));
                ParameterExpression selectPe = Expression.Parameter(resultType, "spe");
                Expression selectMe = Expression.Property(selectPe, resultType.GetProperty(sourceType.Name));
                Type dt4 = typeof(Func<,>).MakeGenericType(resultType, sourceType);
                var q = (IQueryable<T>)selectMany.Provider.CreateQuery(
                    Expression.Call(
                    typeof(Queryable), "Select",
                    new Type[] { resultType, sourceType },
                    selectMany.Expression, Expression.Quote(Expression.Lambda(dt4, selectMe, selectPe))));
                return (IQueryable<T>)q.Provider.CreateQuery(
                    Expression.Call(
                    typeof(Queryable), "Distinct",
                    new Type[] { sourceType },
                    q.Expression));
            }
            pe = Expression.Parameter(sourceType, "it");
            exp = expression.ToExpression(sourceType, pe);
            return (IQueryable<T>)source.Provider.CreateQuery(
                Expression.Call(
                    typeof(Queryable), "Where",
                    new Type[] { sourceType },
                    source.Expression, Expression.Quote(Expression.Lambda<Func<T, bool>>(exp, pe))));
        }
        private static List<DynamicProperty> GetCollectionProperty(SuuchaExpression expression, Type sourceType)
        {
            List<DynamicProperty> list = new List<DynamicProperty>();
            SuuchaBinaryExpression sbe = expression as SuuchaBinaryExpression;
            if (sbe == null)
            {
                return list;
            }

            if (sbe.Left.NodeType == SuuchaExpressionType.Member && sbe.Right.NodeType == SuuchaExpressionType.Constant)
            {
                SuuchaMemberExpression sme = sbe.Left as SuuchaMemberExpression;

                string[] ms = sme.Name.Split(".".ToCharArray());
                Type declareType = sourceType;
                bool hasSetMember = false;
                string setMemberName = "";
                string errorMsg = sourceType.Name.Substring(0, 1).ToLower() + sourceType.Name.Substring(1);
                for (int i = 0; i < ms.Length; i++)
                {
                    errorMsg += "." + ms[i];
                    PropertyInfo pi = declareType.GetPropertyEx(ms[i]);

                    if (pi != null)
                    {
                        declareType = pi.PropertyType;
                        if (declareType != typeof(string))
                        {
                            bool isCollection = false;
                            isCollection = declareType.GetInterface("IEnumerable", true) != null;
                            if (!isCollection)
                            {
                                isCollection = declareType.GetInterface("IEnumerable`1", true) != null;
                            }
                            if (isCollection)
                            {
                                if (!hasSetMember)
                                {
                                    hasSetMember = true;
                                    setMemberName = ms[i];
                                    list.Add(new DynamicProperty(setMemberName, declareType.GetGenericArguments()[0]));
                                }
                                declareType = declareType.GetGenericArguments()[0];
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(Resources.Resource("无效的属性：{0}", errorMsg));
                    }
                }
                if (hasSetMember)
                {
                    if (!sme.Name.StartsWith(setMemberName + "."))
                    {
                        throw new InvalidOperationException(Resources.Resource("无效的属性：{0}", setMemberName));
                    }
                    return list;
                }
            }
            foreach (var p in GetCollectionProperty(sbe.Left, sourceType))
            {
                if (list.FirstOrDefault(l => l.Type == p.Type && l.Name == p.Name) == null)
                {
                    list.Add(p);
                }
            }
            foreach (var p in GetCollectionProperty(sbe.Right, sourceType))
            {
                if (list.FirstOrDefault(l => l.Type == p.Type && l.Name == p.Name) == null)
                {
                    list.Add(p);
                }
            }
            return list;
        }
        /// <summary>
        /// 支持SuuchaOrderBy的OrderBy扩展方法
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="source">源Queryable</param>
        /// <param name="orderBy">SuuchaOrderBy列表</param>
        /// <returns>返回Queryable</returns>
        public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, IEnumerable<SuuchaOrderBy> orderBy)
        {
            if (orderBy == null)
            {
                return source;
            }
            string methodAsc = "OrderBy";
            string methodDesc = "OrderByDescending";
            Expression queryExpr = source.Expression;
            ParameterExpression pe = Expression.Parameter(source.ElementType, "it");
            foreach (SuuchaOrderBy by in orderBy)
            {
                Expression selector = by.Member.ToExpression(source.ElementType, pe);
                Expression lambda = Expression.Quote(Expression.Lambda(selector, pe));
                if (selector.Type.IsValueType || selector.Type == typeof(string))
                {
                    queryExpr = Expression.Call(
                    typeof(Queryable), by.Asc ? methodAsc : methodDesc,
                    new Type[] { source.ElementType, selector.Type },
                    queryExpr, lambda);
                    methodAsc = "ThenBy";
                    methodDesc = "ThenByDescending";
                }
                else
                {
                    throw new InvalidOperationException(Resources.Resource("不支持的排序类型：{0}", selector.Type.FullName));
                }
            }
            return source.Provider.CreateQuery<T>(queryExpr);
        }

        /// <summary>
        /// 支持SuuchaOrderBy的OrderBy扩展方法
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="source">源Queryable</param>
        /// <param name="orderBy">SuuchaOrderBy列表</param>
        /// <returns>返回Queryable</returns>
        public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, IEnumerable<SuuchaOrderBy<T>> orderBy)
        {
            if (orderBy == null)
            {
                return source;
            }
            string methodAsc = "OrderBy";
            string methodDesc = "OrderByDescending";
            Expression queryExpr = source.Expression;
            foreach (SuuchaOrderBy<T> by in orderBy)
            {
                MemberExpression selector = (by.Selector as LambdaExpression).Body.RemoveConvert() as MemberExpression;
                if (selector == null)
                {
                    throw new InvalidOperationException(Resources.Resource("不支持的排序类型"));
                }
                Type resultType = selector.Type;

                Expression exp = Expression.Quote(Expression.Lambda(selector, selector.Parameter()));
                if (resultType.IsValueType || resultType == typeof(string))
                {
                    queryExpr = Expression.Call(
                    typeof(Queryable), by.Asc ? methodAsc : methodDesc,
                    new Type[] { source.ElementType, resultType },
                    queryExpr, exp);
                    methodAsc = "ThenBy";
                    methodDesc = "ThenByDescending";
                }
                else
                {
                    throw new InvalidOperationException(Resources.Resource("不支持的排序类型：{0}", resultType.FullName));
                }

            }
            return source.Provider.CreateQuery<T>(queryExpr);
        }

        private static ParameterExpression Parameter(this MemberExpression expression)
        {
            ParameterExpression parameter = expression.Expression as ParameterExpression;
            if (parameter != null)
            {
                return parameter;
            }
            MemberExpression member = expression.Expression as MemberExpression;
            if (member == null)
            {
                throw new InvalidOperationException(Resources.Resource("不支持的排序类型"));
            }
            return Parameter(member);
        }
        private static Expression RemoveConvert(this Expression expression)
        {
            while (expression != null && (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked))
            {
                expression = ((UnaryExpression)expression).Operand.RemoveConvert();
            }
            return expression;
        }

        /// <summary>
        /// 获取给定的MemberExpression的类型
        /// </summary>
        /// <param name="member">MemberExpression实例</param>
        /// <returns>member的类型</returns>
        public static Type MemberType(this MemberExpression member)
        {
            if (member == null)
            {
                throw new ArgumentNullException("member");
            }
            if (!member.Type.IsNullableType())
            {
                return member.Type;
            }
            return member.Type.GetNonNullableType();
        }
        #region SuuchaExpression Extends
        public static Expression ToExpression(this SuuchaExpression expression, Type sourceType, ParameterExpression pe)
        {
            if (expression == null)
            {
                return null;
            }
            Expression exp = ToExpression(expression, sourceType, pe, null, null, null);
            return exp;
        }

        private static Expression ToExpression(SuuchaExpression expression, Type sourceType, ParameterExpression pe, Expression member, string sourcePrefix, string setPrefix)
        {
            if (expression == null)
            {
                return null;
            }
            Expression exp = null;
            Type memberType = null;
            if (member != null)
            {
                memberType = member.Type;
            }
            if (memberType == null)
            {
                memberType = sourceType;
            }
            SuuchaMemberExpression sme = null;
            SuuchaBinaryExpression sbe = expression as SuuchaBinaryExpression;

            Expression left = null;
            Expression right = null;

            if (sbe != null)
            {
                if ((sbe.Left.NodeType == SuuchaExpressionType.Member && sbe.Right.NodeType == SuuchaExpressionType.Constant)
                    || (sbe.Left.NodeType == SuuchaExpressionType.Constant && sbe.Right.NodeType == SuuchaExpressionType.Member))
                {
                    if (sbe.Left.NodeType == SuuchaExpressionType.Member)
                    {
                        left = ToExpression(sbe.Left, sourceType, pe, null, sourcePrefix, setPrefix);
                        if (sbe.NodeType != SuuchaExpressionType.In && sbe.NodeType != SuuchaExpressionType.InLike)
                        {
                            right = ToExpression(sbe.Right, sourceType, pe, left, sourcePrefix, setPrefix);
                        }
                    }
                    else
                    {
                        right = ToExpression(sbe.Left, sourceType, pe, null, sourcePrefix, setPrefix);
                        if (sbe.NodeType != SuuchaExpressionType.In && sbe.NodeType != SuuchaExpressionType.InLike)
                        {
                            left = ToExpression(sbe.Right, sourceType, pe, right, sourcePrefix, setPrefix);
                        }
                    }
                }
                else
                {
                    left = ToExpression(sbe.Left, sourceType, pe, null, sourcePrefix, setPrefix);
                    right = ToExpression(sbe.Right, sourceType, pe, null, sourcePrefix, setPrefix);
                }
            }
            string str;
            string typeName;
            string[] values;
            SuuchaConstantExpression sce1;
            switch (expression.NodeType)
            {
                case SuuchaExpressionType.Member:
                    sme = expression as SuuchaMemberExpression;
                    if (exp == null)
                    {
                        exp = pe;
                    }
                    string[] members = sme.Name.Split(".".ToCharArray());
                    PropertyInfo pi;
                    for (int i = 0; i < members.Length; i++)
                    {
                        if (i == 0)
                        {
                            string memberName = members[i];
                            if (!string.IsNullOrEmpty(sourcePrefix))
                            {
                                if (memberName != setPrefix)
                                {
                                    pi = exp.Type.GetPropertyEx(sourcePrefix);
                                    exp = Expression.Property(exp, pi);
                                }
                                else
                                {
                                    pi = exp.Type.GetPropertyEx(setPrefix);
                                    exp = Expression.Property(exp, pi);
                                    i++;
                                    memberName = members[i];
                                }

                            }

                            pi = exp.Type.GetPropertyEx(memberName);
                            if (pi == null)
                            {
                                throw new InvalidOperationException(Resources.Resource("无效的属性：{0}", sme.Name));
                            }
                            exp = Expression.Property(exp, pi);
                        }
                        else
                        {
                            Type type1 = exp.Type;
                            pi = type1.GetPropertyEx(members[i]);
                            if (pi != null)
                            {
                                exp = Expression.Property(exp, pi);
                            }
                            else
                            {
                                throw new InvalidOperationException(Resources.Resource("无效的属性：{0}", sme.Name));
                            }
                        }
                    }
                    break;
                case SuuchaExpressionType.And:
                    exp = Expression.AndAlso(left, right);
                    break;
                case SuuchaExpressionType.Or:
                    exp = Expression.OrElse(left, right);
                    break;
                case SuuchaExpressionType.GreaterThan:
                    if (left.Type == typeof(string))
                    {
                        exp = ConvertStringCompareTo(left, SuuchaExpressionType.GreaterThan, right);
                    }
                    else
                    {
                        exp = Expression.GreaterThan(left, right);
                    }
                    break;
                case SuuchaExpressionType.GreaterThanOrEqual:
                    if (left.Type == typeof(string))
                    {
                        exp = ConvertStringCompareTo(left, SuuchaExpressionType.GreaterThanOrEqual, right);
                    }
                    else
                    {
                        exp = Expression.GreaterThanOrEqual(left, right);
                    }
                    break;
                case SuuchaExpressionType.LessThan:
                    if (left.Type == typeof(string))
                    {
                        exp = ConvertStringCompareTo(left, SuuchaExpressionType.LessThan, right);
                    }
                    else
                    {
                        exp = Expression.LessThan(left, right);
                    }
                    break;
                case SuuchaExpressionType.LessThanOrEqual:
                    if (left.Type == typeof(string))
                    {
                        exp = ConvertStringCompareTo(left, SuuchaExpressionType.LessThanOrEqual, right);
                    }
                    else
                    {
                        exp = Expression.LessThanOrEqual(left, right);
                    }
                    break;
                case SuuchaExpressionType.Equal:
                    exp = Expression.Equal(left, right);
                    break;
                case SuuchaExpressionType.NotEqual:
                    exp = Expression.NotEqual(left, right);
                    break;
                case SuuchaExpressionType.Like:
                case SuuchaExpressionType.NotLike:
                    exp = ConvertLike(right, sbe.NodeType, left);
                    break;
                case SuuchaExpressionType.In:
                    sce1 = sbe.Right as SuuchaConstantExpression;
                    if (sce1 == null)
                    {
                        throw new InvalidOperationException(Resources.Resource("In操作符需要右边是字符串常量表达式"));
                    }
                    str = sce1.Value as string;
                    if (string.IsNullOrEmpty(str))
                    {
                        throw new InvalidOperationException(Resources.Resource("In操作符右边字符串常量为空"));
                    }
                    values = str.Split(",".ToCharArray());
                    for (int i = 0; i < values.Length; i++)
                    {
                        if (string.IsNullOrEmpty(values[i]))
                        {
                            continue;
                        }
                        SuuchaConstantExpression valueEx = SuuchaExpression.Constant(values[i]);
                        if (i == 0)
                        {
                            exp = Expression.Equal(left, ToExpression(valueEx, sourceType, pe, left, sourcePrefix, setPrefix));
                        }
                        else
                        {
                            exp = Expression.OrElse(exp, Expression.Equal(left, ToExpression(valueEx, sourceType, pe, left, sourcePrefix, setPrefix)));
                        }
                    }
                    break;
                case SuuchaExpressionType.InLike:
                    sce1 = sbe.Right as SuuchaConstantExpression;
                    if (sce1 == null)
                    {
                        throw new InvalidOperationException(Resources.Resource("InLike操作符需要右边是字符串常量表达式"));
                    }
                    str = sce1.Value as string;
                    if (string.IsNullOrEmpty(str))
                    {
                        throw new InvalidOperationException(Resources.Resource("InLike操作符右边字符串常量为空"));
                    }
                    values = str.Split(",".ToCharArray());
                    for (int i = 0; i < values.Length; i++)
                    {
                        if (string.IsNullOrEmpty(values[i]))
                        {
                            continue;
                        }
                        SuuchaConstantExpression valueEx = SuuchaExpression.Constant(values[i]);
                        if (i == 0)
                        {
                            exp = ConvertLike(ToExpression(valueEx, sourceType, pe, (MemberExpression)left, sourcePrefix, setPrefix), SuuchaExpressionType.Like, left);
                        }
                        else
                        {
                            exp = Expression.OrElse(exp, ConvertLike(ToExpression(valueEx, sourceType, pe, (MemberExpression)left, sourcePrefix, setPrefix), SuuchaExpressionType.Like, left));
                        }
                    }
                    break;
                case SuuchaExpressionType.Constant:
                    SuuchaConstantExpression sce = expression as SuuchaConstantExpression;
                    if (sce.Value == null)
                    {
                        exp = Expression.Constant(null);
                        break;
                    }
                    if (memberType == null)
                    {
                        exp = Expression.Constant(sce.Value);
                        break;
                    }
                    typeName = memberType.Name.Substring(memberType.Name.LastIndexOf(".") + 1);
                    bool isEnum = memberType.IsEnum;
                    Type[] types = memberType.GetGenericArguments();
                    if (types.Length > 0)
                    {
                        typeName = types[0].Name.Substring(types[0].Name.LastIndexOf(".") + 1);
                        isEnum = types[0].IsEnum;
                    }
                    if (isEnum)
                    {
                        exp = Expression.Constant(DynamicCastType.Cast(Convert.ToInt16(sce.Value), memberType), memberType);
                    }
                    else
                    {
                        switch (typeName)
                        {
                            case "Boolean":
                                exp = Expression.Constant(Convert.ToBoolean(sce.Value), memberType);
                                break;
                            case "Byte":
                                exp = Expression.Constant(Convert.ToByte(sce.Value), memberType);
                                break;
                            case "DateTime":
                                exp = Expression.Constant(Convert.ToDateTime(sce.Value), memberType);
                                break;
                            case "Decimal":
                                exp = Expression.Constant(Convert.ToDecimal(sce.Value), memberType);
                                break;
                            case "Double":
                                exp = Expression.Constant(Convert.ToDouble(sce.Value), memberType);
                                break;
                            case "Guid":
                                Guid guid;
                                if (sce.Value.GetType() == typeof(Guid))
                                {
                                    guid = (Guid)sce.Value;
                                }
                                else
                                {
                                    guid = new Guid(Convert.ToString(sce.Value));
                                }
                                exp = Expression.Constant(guid, memberType);
                                break;
                            case "Int16":
                                exp = Expression.Constant(Convert.ToInt16(sce.Value), memberType);
                                break;
                            case "Int32":
                                exp = Expression.Constant(Convert.ToInt32(sce.Value), memberType);
                                break;
                            case "Int64":
                                exp = Expression.Constant(Convert.ToInt64(sce.Value), memberType);
                                break;
                            case "SByte":
                                exp = Expression.Constant(Convert.ToSByte(sce.Value), memberType);
                                break;
                            case "Single":
                                exp = Expression.Constant(Convert.ToSingle(sce.Value), memberType);
                                break;
                            case "String":
                                exp = Expression.Constant(Convert.ToString(sce.Value), memberType);
                                break;
                            default:
                                exp = Expression.Constant(sce.Value);
                                break;
                        }
                    }
                    break;
            }
            return exp;
        }

        private static Expression ConvertStringCompareTo(Expression left, SuuchaExpressionType nodeType, Expression right)
        {
            ConstantExpression ce = right as ConstantExpression;
            Expression expression = null;
            if (right != null)
            {
                string value = ce.Value as string;
                if (!string.IsNullOrEmpty(value))
                {
                    ConstantExpression ce1 = Expression.Constant(value, typeof(string));
                    expression = Expression.Call(left, typeof(string).GetMethod("CompareTo", new Type[] { typeof(string) }), ce1);
                    switch (nodeType)
                    {
                        case SuuchaExpressionType.GreaterThan:
                            expression = Expression.GreaterThan(expression, Expression.Constant(0));
                            break;
                        case SuuchaExpressionType.GreaterThanOrEqual:
                            expression = Expression.GreaterThanOrEqual(expression, Expression.Constant(0));
                            break;
                        case SuuchaExpressionType.LessThan:
                            expression = Expression.LessThan(expression, Expression.Constant(0));
                            break;
                        case SuuchaExpressionType.LessThanOrEqual:
                            expression = Expression.LessThanOrEqual(expression, Expression.Constant(0));
                            break;
                    }
                }
            }
            return expression;
        }

        private static Expression ConvertLike(Expression exp, SuuchaExpressionType nodeType, Expression left)
        {
            ConstantExpression ce = exp as ConstantExpression;
            Expression expression = null;
            if (ce != null)
            {
                string value = ce.Value as string;
                if (!string.IsNullOrEmpty(value))
                {
                    string methodName = "Contains";
                    if (value.StartsWith("%") && value.EndsWith("%"))
                    {
                        methodName = "Contains";
                    }
                    else if (value.EndsWith("%"))
                    {
                        methodName = "StartsWith";
                    }
                    else if (value.StartsWith("%"))
                    {
                        methodName = "EndsWith";
                    }
                    ConstantExpression ce1 = Expression.Constant(value.Replace("%", ""), typeof(string));
                    expression = Expression.Call(left, typeof(string).GetMethod(methodName, new Type[] { typeof(string) }), ce1);
                    if (nodeType == SuuchaExpressionType.NotLike)
                    {
                        expression = Expression.Not(expression);
                    }
                }
            }
            return expression;
        }
        #endregion

        #region SuuchaExpression的Json扩展方法

        /// <summary>
        /// 将SuuchaExpression序列化成一个json
        /// </summary>
        /// <param name="expression">需要序列化的SuuchaExpression</param>
        /// <returns>json字符串</returns>
        public static string ToJson(this SuuchaExpression expression)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(expression);
        }
        /// <summary>
        /// 将SearchParementers 序列化成一个json字符串
        /// </summary>
        /// <param name="search">search</param>
        /// <returns>json字符串</returns>
        public static string ToJson(this SearchParameters search)
        {
            return JsonConvert.SerializeObject(search);
        }
        #endregion

        #region SuuchaOrderBy扩展方法
        /// <summary>
        /// ThenBy方法
        /// </summary>
        /// <param name="orderBy">已有排序</param>
        /// <param name="name">排序属性名称</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy> ThenBy(this IEnumerable<SuuchaOrderBy> orderBy, string name)
        {
            List<SuuchaOrderBy> list = new List<SuuchaOrderBy>(orderBy);
            list.Add(new SuuchaOrderBy(name, true));
            return list;
        }
        /// <summary>
        /// ThenByDescending
        /// </summary>
        /// <param name="orderBy">已有的排序</param>
        /// <param name="name">排序属性名称</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy> ThenByDescending(this IEnumerable<SuuchaOrderBy> orderBy, string name)
        {
            List<SuuchaOrderBy> list = new List<SuuchaOrderBy>(orderBy);
            list.Add(new SuuchaOrderBy(name, false));
            return list;
        }
        /// <summary>
        /// ThenBy方法
        /// </summary>
        /// <param name="orderBy">已有排序</param>
        /// <param name="member">排序成员</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy> ThenBy(this IEnumerable<SuuchaOrderBy> orderBy, SuuchaMemberExpression member)
        {
            List<SuuchaOrderBy> list = new List<SuuchaOrderBy>(orderBy);
            list.Add(new SuuchaOrderBy(member, true));
            return list;
        }
        /// <summary>
        /// ThenByDescending方法
        /// </summary>
        /// <param name="orderBy">已有排序</param>
        /// <param name="member">排序成员</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy> ThenByDescending(this IEnumerable<SuuchaOrderBy> orderBy, SuuchaMemberExpression member)
        {
            List<SuuchaOrderBy> list = new List<SuuchaOrderBy>(orderBy);
            list.Add(new SuuchaOrderBy(member, false));
            return list;
        }
        /// <summary>
        /// 强类型的ThenBy方法
        /// </summary>
        /// <typeparam name="T">需要排序的类型</typeparam>
        /// <param name="orderBy">已有排序</param>
        /// <param name="selector">属性选择</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy<T>> ThenBy<T>(this IEnumerable<SuuchaOrderBy<T>> orderBy, Expression<Func<T, object>> selector)
        {
            List<SuuchaOrderBy<T>> list = new List<SuuchaOrderBy<T>>(orderBy);
            list.Add(new SuuchaOrderBy<T>(selector, true));
            return list;
        }
        /// <summary>
        /// 强类型的ThenByDescending方法
        /// </summary>
        /// <typeparam name="T">需要排序的类型</typeparam>
        /// <param name="orderBy">已有排序</param>
        /// <param name="selector">属性选择</param>
        /// <returns>返回排序列表</returns>
        public static List<SuuchaOrderBy<T>> ThenByDescending<T>(this IEnumerable<SuuchaOrderBy<T>> orderBy, Expression<Func<T, object>> selector)
        {
            List<SuuchaOrderBy<T>> list = new List<SuuchaOrderBy<T>>(orderBy);
            list.Add(new SuuchaOrderBy<T>(selector, false));
            return list;
        }
        #endregion
    }
}
